import { Logger, LogLevel, ValidationPipe } from '@nestjs/common'
import { ConfigService } from '@nestjs/config'
import { AbstractHttpAdapter, NestFactory } from '@nestjs/core'
import { NatsOptions, Transport } from '@nestjs/microservices'
import { FastifyAdapter, NestFastifyApplication } from '@nestjs/platform-fastify'
import { exceptionFactory } from './exception.factory'

// used to create new applications more easily
export class BoticordFactory {
  static async create
    (
      root: any,
      title: string,
      description: string,
      endpoint: string,
      adapter: AbstractHttpAdapter = new FastifyAdapter({ ignoreTrailingSlash: true }),
    ) {
    const app = await NestFactory.create<NestFastifyApplication>(root, adapter, {
      logger: (process.env.APP_LOGS ?? 'log,error,warn,debug,verbose').split(',') as LogLevel[],
    })
    const config = app.get(ConfigService)
    const mig = config.get<string>('RUN_MIGRATION')
    if (mig !== undefined && mig !== 'no') {
      new Logger('BoticordFactory').log('Migration mode enabled, disabling this service for safety purposes.')
      process.exit(0)
    }

    // const exceptionFactiry = (errors: ValidationError[]) => {
    //   return new BadRequestException({
    //     ok: false,
    //     result: null,
    //     service: process.env.BOTICORD_SERVICE ?? 'unknown',
    //     errors: errors.map(e => {
    //       const code = e?.contexts?.['']
    //         ?? e?.value
    //         ?? resolveCodeByHttp(exception?.getStatus?.())
    //         ?? ErrorCodes.UnknownError
    //       return {
    //         code,
    //         message:
    //           (typeof e === 'string' && code !== 0 ? e : undefined)
    //           ?? e.message
    //           ?? errorMessages[code]
    //           ?? errorMessages[ErrorCodes.UnknownError],
    //       }
    //   }}
    // }

    app.useGlobalPipes(new ValidationPipe({ exceptionFactory }))
    app.enableCors({
      origin: '*',
    })
    app.enableShutdownHooks()

    const register = app.getHttpAdapter().getInstance().register
    if (register) {
      register(await import('fastify-multipart'))
    }

    const micro = await app.connectMicroservice<NatsOptions>({
      transport: Transport.NATS,
      options: {
        servers: config.getOrThrow('NATS_SERVERS').split(','),
      },
    })

    micro.useGlobalPipes(new ValidationPipe())

    return {
      app,
      config,
      start: async () => {
        await app.startAllMicroservices()
        await app.listen(config.getOrThrow('APP_PORT'), config.getOrThrow('APP_HOST'))
      },
      init: async () => {
        await app.startAllMicroservices()
        await app.init()
      },
    }
  }
}
